package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"path/filepath"
	"strings"

	"github.com/valyala/fasthttp"
)

// 简单的字符串提取函数
func extractValue(s, key string) string {
	keyStart := strings.Index(s, "\""+key+"\":")
	if keyStart == -1 {
		return ""
	}
	valStart := keyStart + len("\""+key+"\":")
	// 处理引号包围的值
	if valStart < len(s) && s[valStart] == '"' {
		valStart++
		valEnd := strings.Index(s[valStart:], "\"")
		if valEnd != -1 {
			return s[valStart : valStart+valEnd]
		}
	}
	return ""
}

// 预登录处理函数
func preloginHandler(ctx *fasthttp.RequestCtx) {
	// 尝试从JSON解析
	var loginName string

	if bytes.Equal(ctx.Request.Header.ContentType(), []byte("application/json")) {
		// 简单的JSON解析示例
		body := string(ctx.PostBody())
		if strings.Contains(body, "loginName") {
			loginName = extractValue(body, "loginName")

		}
	}
	if loginName == "" { // 尝试从表单解析
		if bytes.Contains(ctx.Request.Header.ContentType(), []byte("application/x-www-form-urlencoded")) {
			loginName = string(ctx.PostArgs().Peek("loginName"))
		}
	}
	if loginName == "" { // 登录名为空
		ctx.SetStatusCode(fasthttp.StatusBadRequest)
		ctx.WriteString(`{"error": 9, "info": "Invalid request format"}`)
		return
	}

	// 验证用户凭据
	user, exists := findUser(loginName)
	if !exists {
		ctx.SetStatusCode(fasthttp.StatusUnauthorized)
		ctx.WriteString(fmt.Sprintf(`{"error": 10, "info": "User %s not found"}`, loginName))
		return
	}

	loginPass := user.Password
	saltType, _, serverSalt, err := passwdto_salt(loginPass)
	if err != nil {
		ctx.SetStatusCode(fasthttp.StatusBadRequest)
		ctx.WriteString(fmt.Sprintf(`{"error": 11, "info": "Password salt error: %s"}`, err.Error()))
		return
	}
	sessionSalt, err := to_salt(saltType)

	success := updateUserSessionSalt(user.LoginName, sessionSalt)
	if !success {
		ctx.SetStatusCode(fasthttp.StatusInternalServerError)
		ctx.WriteString(`{"error": 14, "info": "Failed to update session salt"}`)
		return
	}

	if err != nil {
		ctx.SetStatusCode(fasthttp.StatusBadRequest)
		ctx.WriteString(fmt.Sprintf(`{"error": 12, "info": "Session salt error: %s"}`, err.Error()))
		return
	}

	// 返回成功响应
	response := map[string]interface{}{
		"error":       0,
		"info":        "OK",
		"saltType":    saltType,
		"serverSalt":  serverSalt,
		"sessionSalt": sessionSalt,
	}

	jsonResponse, err := json.Marshal(response)
	if err != nil {
		ctx.SetStatusCode(fasthttp.StatusInternalServerError)
		ctx.WriteString(fmt.Sprintf(`{"error": 13, "info": "JSON marshal error: %s"}`, err.Error()))
		return
	}

	ctx.SuccessString("application/json", string(jsonResponse))
}

// 登录处理函数
func loginHandler(ctx *fasthttp.RequestCtx) {
	// 只允许POST请求
	if !ctx.IsPost() {
		ctx.SetStatusCode(fasthttp.StatusMethodNotAllowed)
		ctx.WriteString(`{"status": "error", "message": "Method not allowed"}`)
		return
	}

	// 尝试从JSON解析
	var loginName string
	var passwd2 string
	if bytes.Equal(ctx.Request.Header.ContentType(), []byte("application/json")) {
		// 简单的JSON解析示例
		body := string(ctx.PostBody())
		if strings.Contains(body, "loginName") {
			loginName = extractValue(body, "loginName")

		}
		if strings.Contains(body, "passwd") {
			passwd2 = extractValue(body, "passwd")
		}
	}
	if loginName == "" || passwd2 == "" { // 尝试从表单解析
		if bytes.Contains(ctx.Request.Header.ContentType(), []byte("application/x-www-form-urlencoded")) {
			loginName = string(ctx.PostArgs().Peek("loginName"))
			passwd2 = string(ctx.PostArgs().Peek("passwd"))
		}
	}
	if loginName == "" || passwd2 == "" { // 登录名为空
		ctx.WriteString(`{"error": 9, "info": "Invalid request format"}`)
		return
	}

	// 获取登录信息
	user, exists := findUser(loginName)
	if !exists {
		ctx.WriteString(fmt.Sprintf(`{"error": 10, "info": "User %s not found"}`, loginName))
		return
	}

	// 获取并校验会话盐值
	sessionSalt := user.sessionSalt

	// 获取登录密码
	loginPass := user.Password

	// 获取密码盐信息
	_, _, _, err := passwdto_salt(loginPass)
	if err != nil {
		ctx.WriteString(fmt.Sprintf(`{"error": 11, "info": "Password salt error: %s"}`, err.Error()))
		return
	}

	// 验证密码（使用两次加密的逻辑：serverSalt + sessionSalt）
	if !passwdCheckWithto_salt(loginPass, passwd2, sessionSalt) {
		ctx.WriteString(`{"error": 99, "info": "Incorrect password"}`)
		return
	}

	// 登录成功
	response := map[string]interface{}{
		"error": 0,
		"info":  "Login successful",
		"user":  loginName,
	}

	jsonResponse, err := json.Marshal(response)
	if err != nil {
		ctx.SetStatusCode(fasthttp.StatusInternalServerError)
		ctx.WriteString(fmt.Sprintf(`{"error": 13, "info": "JSON marshal error: %s"}`, err.Error()))
		return
	}

	ctx.SuccessString("application/json", string(jsonResponse))
}

// 健康检查端点
func healthHandler(ctx *fasthttp.RequestCtx) {
	ctx.SetStatusCode(fasthttp.StatusOK)
	ctx.WriteString(`{"status": "ok", "message": "Server is running"}`)
}

// 中间件：记录请求日志
func loggingMiddleware(next fasthttp.RequestHandler) fasthttp.RequestHandler {
	return func(ctx *fasthttp.RequestCtx) {
		log.Printf("%s %s", ctx.Method(), ctx.Path())
		next(ctx)
	}
}

func main() {
	for _, user := range users {
		if !PasswdCheck(user.Password, user.RelPassword) {
			log.Printf("Password check failed for user %s", user.LoginName)
		} else {
			log.Printf("Password check passed for user %s", user.LoginName)
		}
	}

	// 创建路由
	router := func(ctx *fasthttp.RequestCtx) {
		path := string(ctx.Path())

		// 首先尝试静态文件服务
		fileExtension := filepath.Ext(path)
		if fileExtension == ".html" || fileExtension == ".css" || fileExtension == ".js" || fileExtension == ".png" || fileExtension == ".jpg" || fileExtension == ".jpeg" || fileExtension == ".gif" || fileExtension == ".svg" || fileExtension == ".ico" {
			// 尝试提供当前目录下的静态文件
			if path == "/" {
				path = "/login.html"
			}

			// 去除前导斜杠
			filePath := strings.TrimPrefix(path, "/")

			fasthttp.ServeFileUncompressed(ctx, filePath)
			return
		}

		switch path {
		case "/api/prelogin":
			preloginHandler(ctx)
		case "/api/login":
			loginHandler(ctx)
		case "/health":
			healthHandler(ctx)
		default:
			ctx.SetStatusCode(fasthttp.StatusNotFound)
			ctx.WriteString(`{"status": "error", "message": "Endpoint not found"}`)
		}
	}

	// 应用中间件
	logger := loggingMiddleware(router)

	// 启动服务器
	address := ":8082"
	log.Printf("Server starting on %s", address)
	log.Printf("Login API: POST http://localhost%s/api/login", address)
	log.Printf("Health check: GET http://localhost%s/health", address)
	log.Printf("Static files: http://localhost%s/login.html", address)

	if err := fasthttp.ListenAndServe(address, logger); err != nil {
		log.Fatalf("Error in ListenAndServe: %s", err)
	}
}
